/*******************************************************************************
 * Copyright (c) 2001, 2002 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 *	  David Corbin - added images, MicroPlugin implementation, 
 *                   static getClientName() method
 ******************************************************************************/
package net.sourceforge.perforce.ui;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.PerforceSynchronizer;
import net.sourceforge.perforce.core.internal.api.PerforceServer;
import net.sourceforge.perforce.core.internal.events.AddDeleteMoveListener;
import net.sourceforge.perforce.core.resources.RemoteFile;
import net.sourceforge.perforce.core.resources.RemoteFolder;
import net.sourceforge.perforce.ui.internal.Policy;
import net.sourceforge.perforce.ui.internal.model.P4File;
import net.sourceforge.perforce.ui.model.PerforceAdapterFactory;
import net.sourceforge.perforce.ui.views.Console;

import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPluginDescriptor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.plugin.AbstractUIPlugin;

/**
  * @version  $Revision: 249 $
  * @author   <a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  */
public class PerforceUIPlugin 
	extends AbstractUIPlugin 
	implements MicroPlugin, IPropertyChangeListener, IPerforceUIConstants
{
	// ---------------------------------------------------------------------------- Public Constants
	
	public static final String CALCULATE_DIRTY_PREFERENCE = 
		ID + ".preferences.calculate_dirty";                                           //$NON-NLS-1$
	public static final String DELETE_AFFECTS_CHANGELIST = 
		ID + ".preferences.delete_affects_changelist";                                 //$NON-NLS-1$

	public static final String ICON_PATH_FULL = "icons/full/";                         //$NON-NLS-1$
	public static final String IMG_CLEAR = "clcl16/clear_co.gif";                      //$NON-NLS-1$
	public static final String IMG_ROOTELEMENT = "clcl16/depot.gif";                   //$NON-NLS-1$
	public static final String IMG_REPOSITORY = "cview16/depot_view.gif";              //$NON-NLS-1$
	public static final String IMG_ERROR = "misc/error.gif";                           //$NON-NLS-1$
	public static final String IMG_SUBMITTED_CHANGELIST = "clcl16/submitted_cl.gif";   //$NON-NLS-1$
	
	// -------------------------------------------------------------------- Private Static Variables
	
	private static PerforceUIPlugin instance;
	
	// --------------------------------------------------------------------------- Private Variables
	
	/** Map containing preloaded ImageDescriptors */
	private Map imageDescriptors = new HashMap(24);
	
	// ------------------------------------------------------------------------- Public Constructors
	
	/** Constructor for PerforceUIPlugin.
	  * 
	  * @param descriptor the plugin's descriptor.
	  */
	public PerforceUIPlugin(IPluginDescriptor descriptor)
	{
		super(descriptor);
		
		Policy.assertNull(instance);
		instance = this;	
		MicroPluginFactory.setPlugin(this);
		
		getPreferenceStore().addPropertyChangeListener(this);
	}
	
	// ----------------------------------------------------------------------- Public Static Methods

	/** Returns the plugin's singleton instance.
	  * 
	  * @return the singleton instance. 
	  */
	public static PerforceUIPlugin getPlugin()
	{
		Policy.assertNotNull(instance);
		return instance;
	}
	
	/** Call this method to retrieve the currently active Workbench page.
	  *
	  * @return the active workbench page. 
	  */
	public static IWorkbenchPage getActivePage() 
	{
		IWorkbenchWindow window = getPlugin().getWorkbench().getActiveWorkbenchWindow();		
		if (window == null) 
		{
			return null;
		}
		else
		{
			return window.getActivePage();
		}
	}
	
	/** Call this method to retrieve the shell of the actie workbench window.
	  *
	  * @return the active shell. 
	  */
	public static Shell getActiveShell()
	{
		IWorkbenchWindow window = getPlugin().getWorkbench().getActiveWorkbenchWindow();
		if (window == null) 
		{
			return null;
		}
		else
		{
			return window.getShell();
		}
	}

	/** Returns the workspace instance. 
	  * 
	  * @return the workspace.
	  */
	public static IWorkspace getWorkspace() 
	{
		return ResourcesPlugin.getWorkspace();
	}

	/** Call this method to log the given status.
	  *
	  * @param status the status to log. 
	  */
	public static void log(IStatus status)
	{
		getPlugin().getLog().log(status);
	}

	/** Call this method to log an error with the given message & throwable.
	  *
	  * @param message the message.
	  * @param throwable the exception. 
	  */
	public static void logError(String message, Throwable throwable) 
	{
		getPlugin().getLog().log(
			new Status(IStatus.ERROR, PerforceUIPlugin.ID, IStatus.ERROR, message, throwable));
	}
		
	// ------------------------------------------------------------------------------ Public Methods
	
	/** @see Plugin#startup() */
	public void startup() 
		throws CoreException
	{
		super.startup();		
		Policy.localize("net.sourceforge.perforce.ui.messages");                       //$NON-NLS-1$
	
	
		IStatus status = PerforceSynchronizer.getInstance().getStatus();
		if (!status.isOK())
		{
			ErrorDialog.openError(
					null, 
					Policy.bind("PerforceUIPlugin.synchronizerErrorTitle"),            //$NON-NLS-1$
					Policy.bind("PerforceUIPlugin.synchronizerError"),                 //$NON-NLS-1$
					status, 
					IStatus.INFO | IStatus.ERROR);
		}
		
	
		PerforceAdapterFactory factory = new PerforceAdapterFactory();
		Platform.getAdapterManager().registerAdapters(factory, PerforceServer.class);
		Platform.getAdapterManager().registerAdapters(factory, RemoteFolder.class);
		Platform.getAdapterManager().registerAdapters(factory, RemoteFile.class);
		Platform.getAdapterManager().registerAdapters(factory, P4File.class);
	
		initializeImages();
		initializeCorePreferences();
		
		Console.startup();
	}
	
	/** @see Plugin#shutdown() */
	public void shutdown() 
		throws CoreException
	{
		Console.shutdown();
		PerforceDecorator.shutdown();
		
		super.shutdown();
	}

	/** Call this method to retrieve the (cache) ImageDescriptor for the given id.
	  *
	  * @param id the id of the image descriptor.
	  * @return the ImageDescriptor instance. 
	  */
	public ImageDescriptor getImageDescriptor(String id) 
	{
		return (ImageDescriptor) imageDescriptors.get(id);
	}

	/** Called to retrieve the workspace root.
	  *
	  * @return the workspace root. 
	  */
	public IWorkspaceRoot getWorkspaceRoot()
	{
		return ResourcesPlugin.getWorkspace().getRoot();
	}

	/** @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(PropertyChangeEvent) */
	public void propertyChange(PropertyChangeEvent event) 
	{
		try 
		{
			String property = event.getProperty();
			if (property.equals(PREF_SHOW_TASKS_ON_ADD)) 
			{
				boolean b = ((Boolean) event.getNewValue()).booleanValue();				
				PerforceCorePlugin.getPlugin().setShowTasksOnAdd(b);				
				
				if (b) 
				{
					AddDeleteMoveListener.refreshAllMarkers();
				}
				else
				{
					AddDeleteMoveListener.clearAllPerforceMarkers();
				}
			}
			else
			if (property.equals(DELETE_AFFECTS_CHANGELIST))
			{
				boolean b = ((Boolean) event.getNewValue()).booleanValue();
				PerforceCorePlugin.getPlugin().setDeleteAffectsChangelist(b);
			}
			else
			if (property.equals(PREF_BACKGROUND_UPDATE_INTERVAL))
			{
				int value = ((Integer) event.getNewValue()).intValue();
				PerforceCorePlugin.getPlugin().setBackgroundUpdateInterval(value);
			}
			else
			if (property.equals(PREF_SHOULD_MONITOR_CHANGELISTS))
			{
				boolean b = ((Boolean) event.getNewValue()).booleanValue();
				PerforceCorePlugin.getPlugin().setShouldMonitorChangelists(b);
			}
			else
			if (property.equals(PREF_SHOULD_MONITOR_OPENED_FILES))
			{
				boolean b = ((Boolean) event.getNewValue()).booleanValue();
				PerforceCorePlugin.getPlugin().setShouldMonitorOpenedFiles(b);
			}
		} 
		catch (CoreException e) 
		{
			log(e.getStatus());
		}
	}

	// --------------------------------------------------------------------------- Protected Methods

	/** @see AbstractUIPlugin#initializeDefaultPreferences(IPreferenceStore) */
	protected void initializeDefaultPreferences(IPreferenceStore store)
	{
		store.setDefault(CALCULATE_DIRTY_PREFERENCE, false);
		store.setDefault(DELETE_AFFECTS_CHANGELIST, true);
		
		store.setDefault(PREF_DIRTY_FLAG, P4DecoratorConfiguration.DEFAULT_DIRTY_FLAG);
		store.setDefault(PREF_ADDED_FLAG, P4DecoratorConfiguration.DEFAULT_ADDED_FLAG);
		store.setDefault(PREF_FILETEXTFORMAT, P4DecoratorConfiguration.DEFAULT_FILETEXTFORMAT);
		store.setDefault(PREF_FOLDERTEXTFORMAT,	P4DecoratorConfiguration.DEFAULT_FOLDERTEXTFORMAT);
		store.setDefault(
			PREF_PROJECTTEXTFORMAT, P4DecoratorConfiguration.DEFAULT_PROJECTTEXTFORMAT);			
		store.setDefault(PREF_SHOW_TASKS_ON_ADD, true);
		store.setDefault(PREF_DONT_PROMPT_AUTOMATIC_OPEN, false);
		store.setDefault(PREF_WARN_ON_OTHER_OPEN, false);
		store.setDefault(PREF_CHECK_CHANGELIST_FOR_WARNINGS_AND_ERROR, true);
		store.setDefault(PREF_INDICATE_HAS_REMOTE, true);
		store.setDefault(PREF_INDICATE_NEW_RESOURCE, true);
		store.setDefault(PREF_INDICATE_OPENED_BY_OTHER, true);
		store.setDefault(PREF_INDICATE_OPENED_FOR_ADD, true);
		store.setDefault(PREF_INDICATE_OPENED_FOR_EDIT, true);
		
		// Background Update Defaults
		store.setDefault(PREF_BACKGROUND_UPDATE_INTERVAL, 240);
		store.setDefault(PREF_SHOULD_MONITOR_CHANGELISTS, true);
		store.setDefault(PREF_SHOULD_MONITOR_OPENED_FILES, true);
	}
		
	// --------------------------------------------------------------------------- Private Variables
	
	/** Called to initialize the image cache. */
	private void initializeImages()
	{
		URL baseURL = getDescriptor().getInstallURL();
		
		createImageDescriptor(IMG_CLEAR, baseURL);
		createImageDescriptor(IMG_ROOTELEMENT, baseURL);
		createImageDescriptor(IMG_ERROR, baseURL);
		createImageDescriptor(IMG_REPOSITORY, baseURL);
		createImageDescriptor(IPerforceUIConstants.IMG_REFRESH, baseURL);
		
		
		createImageDescriptor(IPerforceUIConstants.IMG_CLIENT_CHANGELISTS, baseURL);
		createImageDescriptor(IPerforceUIConstants.IMG_CLIENT_CHANGELIST, baseURL);		
		createImageDescriptor(IPerforceUIConstants.IMG_OTHER_CHANGELISTS, baseURL);
		createImageDescriptor(IPerforceUIConstants.IMG_OTHER_CHANGELIST, baseURL);
		createImageDescriptor(IMG_SUBMITTED_CHANGELIST, baseURL);		
		
		createImageDescriptor(IPerforceUIConstants.IMG_PERFORCE_SERVER, baseURL);
		createImageDescriptor(IPerforceUIConstants.IMG_HEAD_REV, baseURL);
		createImageDescriptor(IPerforceUIConstants.IMG_NEWLOCATION, baseURL);
		createImageDescriptor(IPerforceUIConstants.IMG_WIZBAN_SHARE, baseURL);
		
		createImageDescriptor(OVR_HASREMOTE, baseURL);
		createImageDescriptor(OVR_NO_REMOTE, baseURL);
		createImageDescriptor(OVR_OUTOFDATE, baseURL);		
		createImageDescriptor(OVR_OPENFORADD, baseURL);
		createImageDescriptor(OVR_OPENFOREDIT, baseURL);		
		createImageDescriptor(OVR_OPENFORDELETE, baseURL);
		createImageDescriptor(OVR_LOCKED, baseURL);
		
		createImageDescriptor(OVR_OTHER_OPENFORADD, baseURL);
		createImageDescriptor(OVR_OTHER_OPENFORDELETE, baseURL);
		createImageDescriptor(OVR_OTHER_OPENFOREDIT, baseURL);
	}	
	
	/** Called to cache the image descriptor for th given id and baseUrl.
	  *
	  * @param id the id of the image.
	  * @param baseURL the base url 
	  */
	private void createImageDescriptor(String id, URL baseURL) 
	{
		URL url = null;
		try 
		{
			url = new URL(baseURL, ICON_PATH_FULL + id);
		} 
		catch (MalformedURLException e) 
		{
			// Ignored!
		}
		
		ImageDescriptor desc = ImageDescriptor.createFromURL(url);
		imageDescriptors.put(id, desc);
	}	
	
	/** Propagates the preferences to the core plugin. */
	private void initializeCorePreferences()
	{
		IPreferenceStore store = getPreferenceStore();
		
		PerforceCorePlugin corePlugin = PerforceCorePlugin.getPlugin(); 
		corePlugin.setShowTasksOnAdd(store.getBoolean(PREF_SHOW_TASKS_ON_ADD));		
		corePlugin.setDeleteAffectsChangelist(store.getBoolean(DELETE_AFFECTS_CHANGELIST));
		
		corePlugin.setBackgroundUpdateInterval(store.getInt(PREF_BACKGROUND_UPDATE_INTERVAL));
		corePlugin.setShouldMonitorChangelists(store.getBoolean(PREF_SHOULD_MONITOR_CHANGELISTS));
		corePlugin.setShouldMonitorOpenedFiles(store.getBoolean(PREF_SHOULD_MONITOR_OPENED_FILES));
	}
}
